/**
 * 
 */
package com.mixsmart.core.dao.impl;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.type.StandardBasicTypes;
import org.springframework.beans.factory.annotation.Autowired;

import com.mixsmart.core.statement.filter.IStatementFilter;
import com.mixsmart.core.statement.filter.SQLConditionFilter;
import com.mixsmart.exception.NullArgumentException;

/**
 * 与Hibernate相关的DAO类
 * @author lmq
 * @version 1.0
 * @since JDK版本大于等于1.6
 * 2015年12月21日
 */
public abstract class HibernateDao extends SuperDao {

	@Autowired
	private SessionFactory sessionFactory;
	
	/**
	 * 获取数据库连接
	 * @return 数据库连接对象
	 */
	protected Connection getConnection() {
		Connection connection = sessionFactory.getCurrentSession().doReturningWork(
				new ReturningWork<Connection>() {
					@Override
					public Connection execute(Connection conn) throws SQLException {
						return conn;
					}
				}
		);  
		return connection;
	}
	
	/**
	 * 获取数据库session
	 * @return Session对象
	 */
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}
	
	/**
	 * 获取Query对象
	 * @param statement SQL或HQL语句
	 * @param params 参数
	 * @param isSql statement是否为SQL语句
	 * @param isFilter 是否对SQL或HQL过滤
	 * @return 返回Query对象
	 */
	protected Query getQuery(String statement, Map<String,Object> params, boolean isSql, boolean isFilter) {
		assertStatement(statement);
		Query query = null;
		if(isFilter) {
			IStatementFilter filter = new SQLConditionFilter(statement, params);
			filter.filter();
			statement = filter.getStatement();
			params = filter.getParams();
		}
		if(isSql) 
			query = getSession().createSQLQuery(statement);
		else 
			query = getSession().createQuery(statement);
		if(null != params && !params.isEmpty()) 
			query.setProperties(params);
		return query;
	}
	
	/**
	 * SQL查询对象中添加toBeanClass属性
	 * @param sqlQuery SQLQuery对象
	 * @param toBeanClass 转换Bean
	 * @return 返回处理后的SQLQuery对象
	 */
	protected SQLQuery addScalars(SQLQuery sqlQuery, Class<?> toBeanClass){
		if(null == toBeanClass) {
			return sqlQuery;
		}
		List<Field> fields = new ArrayList<Field>();
		getAllFields(fields, toBeanClass);
		for(Field field : fields){
			if(!field.getName().equals("serialVersionUID")){
				if(field.getType() == Integer.class){
					sqlQuery.addScalar(field.getName(), StandardBasicTypes.INTEGER);
				} else if(field.getType() == Double.class){
					sqlQuery.addScalar(field.getName(), StandardBasicTypes.DOUBLE);
				} else if(field.getType() == Long.class){
					sqlQuery.addScalar(field.getName(), StandardBasicTypes.LONG);
				} else if(field.getType() == Float.class){
					sqlQuery.addScalar(field.getName(), StandardBasicTypes.FLOAT);
				} else if(field.getType() == Date.class){
					sqlQuery.addScalar(field.getName(), StandardBasicTypes.DATE);
				} else if(field.getType() == String.class){
					sqlQuery.addScalar(field.getName(), StandardBasicTypes.STRING);
				} else{
					sqlQuery.addScalar(field.getName());
				}
			}
		}
		return sqlQuery;
	}
	
	/**
	 * 执行SQL语句
	 * @param sql SQL语句
	 * @param params 参数
	 * @param isFilter 是否对SQL过滤
	 * @return 成功返回：true；否则返回：false
	 * @throws DaoException
	 */
	protected boolean executeSQL(String sql,HashMap<String,Object> params, boolean isFilter){
		Query query = getQuery(sql, params, true, isFilter);
		return query.executeUpdate()>0?true:false;
	}
	
	/**
	 * 执行HQL语句
	 * @param hql HQL语句
	 * @param params 参数
	 * @param isFilter 是否对SQL过滤
	 * @return 成功返回：true；否则返回：false
	 * @throws DaoException
	 */
	protected boolean executeHQL(String hql,HashMap<String,Object> params, boolean isFilter){
		Query query = getQuery(hql, params, false, isFilter);
		return query.executeUpdate()>0?true:false;
	}
	
	/**
	 * 获取<code>toBeanClass</code>类的所有字段
	 * @param fields 用户存放字段名称的集合
	 * @param toBeanClass 需要获取的对象类
	 */
	private void getAllFields(List<Field> fields,Class<?> toBeanClass) {
		if(null == fields || null == toBeanClass) {
			throw new NullArgumentException();
		}
		Field[] array = toBeanClass.getDeclaredFields();
		if(array.length > 0) {
			fields.addAll(Arrays.asList(array));
		}
		toBeanClass = toBeanClass.getSuperclass();
		if(null != toBeanClass && !(toBeanClass.isAssignableFrom(Object.class))) {
			getAllFields(fields, toBeanClass);
		}
	}
	
}
